package org.spring.springboot.app.mail.mailBind.controller;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.CharacterPredicates;
import org.apache.commons.text.RandomStringGenerator;
import org.spring.springboot.app.base.Constants;
import org.spring.springboot.app.base.R;
import org.spring.springboot.app.base.Type;
import org.spring.springboot.app.base.User;
import org.spring.springboot.app.user.sysuser.domain.vo.MailImageCodeResVO;
import org.spring.springboot.app.user.sysuser.domain.vo.MailSendResVO;
import org.spring.springboot.app.mail.mailBind.domain.vo.MailSendBindVO;
import org.spring.springboot.app.mail.mailBind.domain.vo.UserBindingVO;
import org.spring.springboot.app.mail.mailBind.domain.vo.ValidMailBindVO;
import org.spring.springboot.app.mail.mailBind.service.ISysuBindingService;
import org.spring.springboot.app.user.sysuser.domain.po.SysUserPO;
import org.spring.springboot.app.user.sysuser.service.ISysUserService;
import org.spring.springboot.component.annotation.AccessTokenVerify;
import org.spring.springboot.util.ApiIndex;
import org.spring.springboot.util.IdGen;
import org.spring.springboot.util.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Date;
import java.util.concurrent.TimeUnit;
@Api(description="绑定mail操作接口",tags = ApiIndex.BindEmailController)
@RestController
public class BindEmailController {

    @Autowired
    DefaultKaptcha defaultKaptcha;
    @Autowired
    private ISysuBindingService emailService;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private RedisUtils redisUtils;
    /**
     * 发送验证码
     * email：邮箱账号
     */
    @ApiOperation(value="发送验证码", notes="getEntityById")
    @ApiImplicitParam(name = "token", value = "token", paramType = "query", dataType = "String", required = true)
    @AccessTokenVerify
    @RequestMapping(value = "/api/mail/getTestDemoEmail", method = RequestMethod.PUT)
    public R mainEmail(@RequestBody MailSendBindVO vo,
            @ApiParam(value = "验证码token", required = true) @RequestParam String token,
            @ApiIgnore User user
    ) {
        vo.setLoginId(user.getId());
      //  R<MailSendBindVO> r = new R<MailSendBindVO>();
        R result = new R();
       // SysUserPO po = sysUserDao.findByLoginId(user.getLoginId());

        SysUserPO po = sysUserService.find(user.getId());
        if(!po.getEmail().equals("")){
             result.setType(Type.ParamValidateFail);
            result.addMessage("email", "该用户已绑定"+po.getEmail()+"邮箱！");
            return result;
        }
        if (redisUtils.hasStringKey(Constants.MAIL_SEND_OUT_TIME_REDIS_KEY + user.getId())) {
            result.setType(Type.OperError);
            result.setMessage("验证码每60秒只能发送一次");
            return result;
        }
        String mailCode = redisUtils.getString(Constants.MAIL_SEND_IMAGE_CODE_REDIS_KEY + vo.getImageCaptchaToken());
        if (mailCode == null) {
            result.setType(Type.ParamValidateFail);
            result.addMessage("imageCode", "图片验证码已过期,请点击图片验证码刷新");
            return result;
        }
        if (!mailCode.equalsIgnoreCase(vo.getImageCode())) {
            result.setType(Type.ParamValidateFail);
            result.addMessage("imageCode", "图片验证码不正确");
            return result;
        }
        try {
            //产生验证码
            String generator = new RandomStringGenerator.Builder().withinRange('0','Z').filteredBy(CharacterPredicates.LETTERS,CharacterPredicates.DIGITS).build().generate(4);
            StringBuilder html=new StringBuilder();
            html.append("<html><body><a>验证码:"+generator+"</a></body></html>");
            String uuid = IdGen.uuid();
            emailService.mainEmail("验证码通知",html.toString(),vo.getEmail());
            result.setData(uuid);
            //将验证码和发送验证码时间（60发一次）存入redis并设置有效时间
            redisUtils.setString(Constants.MAIL_SEND_OUT_TIME_REDIS_KEY + user.getId(), new Date().getTime() + "", 60, TimeUnit.SECONDS);
            redisUtils.setString(Constants.MAIL_SEND_CODE_REDIS_KEY + uuid, generator, 10 * 60, TimeUnit.SECONDS);
            return result;
        }catch (Exception e){

        }
        return result;
    }


    /**
     * 绑定用户邮箱
     */
    @ApiOperation(value="绑定用户邮箱")
    @ApiImplicitParam(name = "token", value = "token", paramType = "query", dataType = "String", required = true)
    @AccessTokenVerify
    @RequestMapping(value = "/api/sysUser/modifyBinding", method = RequestMethod.PUT)
    public R modifyBinding(
            @ApiParam(value = "token", required = true) @RequestParam String token,
            @ApiIgnore User user, @RequestBody UserBindingVO vo) {
        R result = new R();
      //  R<UserBindingVO> r = new R<UserBindingVO>();
        if(!result.valid(vo)){
            return result;
        }
        System.out.print(vo.getBindtoken());
        //获取存入redis中的验证码
        String mailCode = redisUtils.getString(Constants.MAIL_SEND_CODE_REDIS_KEY +vo.getBindtoken());
        if (mailCode == null) {
            result.setType(Type.ParamValidateFail);
            result.setMessage("邮箱验证码已过期,请重新发送");
            return result;
        }
        //判断传入的验证码是否与redis中得验证码相同（相同则绑定）
        if (!mailCode.equalsIgnoreCase(vo.getVerificationcode())) {
            result.setType(Type.ParamValidateFail);
            result.setMessage("邮箱验证码错误");
            return result;
        }

        emailService.setBinding(user.getId(), vo.getEmail());
        return result;
    }

    @ApiOperation(value = "发送邮箱")
    @ApiImplicitParam(name = "token", value = "token", paramType = "query", dataType = "String", required = true)
    @AccessTokenVerify
    @RequestMapping(value = "/api/sysUser/sendMailbind", method = RequestMethod.POST)
    public R sendMailbind(@RequestBody MailSendBindVO vo,
                          @ApiParam(value = "token", required = true) @RequestParam String token,
                          @ApiIgnore User user) {
        vo.setLoginId(user.getId());
        return emailService.sendMail(vo);
    }

    /**
     * 验证旧邮箱是否正确
     */
    @ApiOperation(value="验证旧邮箱是否正确")
    @ApiImplicitParam(name = "token", value = "token", paramType = "query", dataType = "String", required = true)
    @AccessTokenVerify
    @RequestMapping(value = "/api/sysUser/verifyingmailbox", method = RequestMethod.GET)
    public R verifyingmailbox(
            @ApiParam(value = "token", required = true) @RequestParam String token,
            @ApiParam(value = "email", required = true) @RequestParam String email,
            @ApiIgnore User user) {
        System.out.print(email);
        R result = new R();
        SysUserPO po = sysUserService.find(user.getId());
        //判断传入的旧邮箱是否与数据中的相同
        if (!email.equals(po.getEmail())) {
            result.setType(Type.ParamValidateFail);
            result.setMessage("邮箱不正确");
            return result;
        }
        return result;
    }

    @ApiOperation(value = "图片访问地址")
    @RequestMapping(value = "/bindcaptcha", method = RequestMethod.GET)
    public void bindcaptcha(@ApiParam(value = "验证码token", required = true) @RequestParam String bindToken, HttpServletResponse httpServletResponse) throws Exception {
        byte[] captchaChallengeAsJpeg = null;
        ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
        try {
            //生产验证码字符串并保存到redis中
            String createText = defaultKaptcha.createText();
            if (StringUtils.isNotBlank(bindToken)) {
                redisUtils.setString(Constants.MAIL_SEND_IMAGE_CODE_REDIS_KEY + bindToken, createText, 5 * 60, TimeUnit.SECONDS);
            }
            //使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中
            BufferedImage challenge = defaultKaptcha.createImage(createText);
            ImageIO.write(challenge, "jpg", jpegOutputStream);
        } catch (IllegalArgumentException e) {
            httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        //定义response输出类型为image/jpeg类型，使用response输出流输出图片的byte数组
        captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
        httpServletResponse.setHeader("Cache-Control", "no-store");
        httpServletResponse.setHeader("Pragma", "no-cache");
        httpServletResponse.setDateHeader("Expires", 0);
        httpServletResponse.setContentType("image/jpeg");
        ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream();
        responseOutputStream.write(captchaChallengeAsJpeg);
        responseOutputStream.flush();
        responseOutputStream.close();
    }

    @ApiOperation(value = "校验邮箱验证码并修改")
    @ApiImplicitParam(name = "token", value = "token", paramType = "query", dataType = "String", required = true)
    @AccessTokenVerify
    @RequestMapping(value = "/api/sysUser/validMailCodeBind", method = RequestMethod.PUT)
    public R<MailSendResVO> validMailCodeBind(
            @ApiParam(value = "token", required = true) @RequestParam String token,
            @ApiIgnore User user,@RequestBody ValidMailBindVO vo) {
        vo.setLoginId(user.getId());
        return emailService.validMailCode(vo);
    }

    @ApiOperation(value = "取得验证码图片token和验证码图片url地址")
    @RequestMapping(value = "/api/sysUser/getCaptchaBind", method = RequestMethod.GET)
    public R<MailImageCodeResVO> captcha(HttpServletRequest request) {
        String path = request.getContextPath();
        String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
        R<MailImageCodeResVO> r = new R<MailImageCodeResVO>();
        String uuid = IdGen.uuid();
        MailImageCodeResVO c = new MailImageCodeResVO();
        c.setImageCaptchaToken(uuid);
        c.setImageCaptchaUrl(basePath + "bindcaptcha?bindToken=" + uuid);
        r.setData(c);
        return r;
    }
}
